﻿using Aga.Controls.Tree;
using Aga.Controls.Tree.NodeControls;
//using Microsoft.SharePoint;
//using Microsoft.SharePoint.Client;
using SPCoder.Config;
using SPCoder.Core.Utils;
using SPCoder.HelperWindows;
using SPCoder.Utils;
using SPCoder.Utils.Nodes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Security;
using System.Text;
using System.Windows.Forms;
using WeifenLuo.WinFormsUI.Docking;

namespace SPCoder.Windows
{
    public partial class ExplorerView : DockContent
    {
        #region Inner classes
        protected class SPTreeViewNode : Node
        {
            public override bool IsLeaf
            {
                get
                {
                    return (Tag is LeafNode);
                }
            }
        }

        private class ToolTipProvider : IToolTipProvider
        {
            public string GetToolTip(TreeNodeAdv node, NodeControl nodeControl)
            {
                return "Drag&Drop nodes to move them to context";
            }
        } 
        #endregion

        public ExplorerView()
        {
            InitializeComponent();
            
            _nodeTextBox.ToolTipProvider = new ToolTipProvider();
            _model = new TreeModel();
            tvSp.Model = _model;
            _childFont = new Font(tvSp.Font.FontFamily, 18, FontStyle.Bold);
            imagesUrlFolder = ConfigUtils.GetRootConfig().Properties.Find(s => s.Name == SPCoderConstants.IMAGES_FOLDER_PATH).Value;

            //probaj da uvezes preko MEF
            foreach (ModuleDescription module in SPCoderForm.MainForm.Modules)
            {
                if (module.ConnectorTypes != null)
                    foreach (string m in module.ConnectorTypes)
                        cbObjectModelType.Items.Add(m);
            }
        }

        private string imagesUrlFolder = "";
        public List<BaseNode> Nodes = new List<BaseNode>();
        //public SPSite Site;
        private TreeModel _model;
        private Font _childFont;
        private string _currentSiteUrl;

        public void Connect(string siteUrl, string omType)
        {
            Connect(siteUrl, omType, null, null);
        }

        public void Connect(string siteUrl, string omType, string username, string password)
        {
            try
            {
                SPCoderForm.MainForm.AppendToLog("Before connecting to: " + siteUrl);
                Application.DoEvents();
                BaseNode rootNode = null;
                ObjectModelType objectModelType = ObjectModelType.SSOM;
                BaseConnector connector = null;

                string selectedType = cbObjectModelType.SelectedItem.ToString();

                foreach (ModuleDescription module in SPCoderForm.MainForm.Modules)
                {
                    if (module.ConnectorTypes != null)                        
                        if (module.ConnectorTypes.Contains(selectedType))                            
                            {
                                connector = module.GetConnector(selectedType);
                                break;
                            }                            
                }
                if (connector == null)
                {
                    SPCoderForm.MainForm.LogError("Cannot connect to: " + siteUrl + ". Connector " + selectedType + " does not exist.");
                    return;
                }

                imagesUrlFolder = ConfigUtils.GetRootConfig().Properties.Find(s => s.Name == SPCoderConstants.IMAGES_FOLDER_PATH).Value;
                //imagesUrlFolder = siteUrl + "/_layouts/images/";

                //Now create tree view stuff;
                rootNode = connector.GetSPStructure(siteUrl);
                tvSp.BeginUpdate();
                CreateAllTreeViewNodes(rootNode, objectModelType);
                tvSp.EndUpdate();
            }
            catch (Exception exc)
            {
                //Log
                SPCoderForm.MainForm.LogException(exc);
            }
            finally
            {
                SPCoderForm.MainForm.AppendToLog("After connecting to: " + siteUrl);
            }
        }

        public void Connect(string siteUrl)
        {
            Connect(siteUrl, "SSOM");
        }

        private void CreateAllTreeViewNodes(BaseNode rootNode, ObjectModelType objectModelType)
        {
            client = new WebClient();
            SPTreeViewNode root = CreateNode(rootNode.Title, "", rootNode, objectModelType);
            _model.Nodes.Add(root);

            CreateTreeViewNode(root, rootNode.Children[0], objectModelType);
            
            client.Dispose();
        }

        private void CreateTreeViewNode(Node tvNode, BaseNode node, ObjectModelType objectModelType)
        {
            SPTreeViewNode myNode = CreateNode(node.Title, node.IconPath, node, objectModelType);
            myNode.Parent = tvNode;
            
            tvNode.Nodes.Add(myNode);
            foreach (BaseNode child in node.Children)
            {
                CreateTreeViewNode(myNode, child, objectModelType);
            }
        }

        Dictionary<string, Bitmap> images = new Dictionary<string, Bitmap>();
        WebClient client;

        private SPTreeViewNode CreateNode(string tekst, string imageUrl, BaseNode o, ObjectModelType modelType)
        {
            Bitmap bitmap = null;
            if (o.IconObject != null)
            {
                bitmap = o.IconObject;
            }
            else
            {
                try
                {
                    if (!string.IsNullOrEmpty(imageUrl))
                    {
                        string[] s = imageUrl.Split('/');
                        if (s.Length > 0)
                            imageUrl = s[s.Length - 1];
                        if (imageUrl.Contains("?"))
                        {
                            imageUrl = imageUrl.Substring(0, imageUrl.IndexOf('?'));
                        }
                        if (images.ContainsKey(imageUrl))
                        {
                            bitmap = images[imageUrl];
                        }
                        else
                        {
                            if (imageUrl.ToLower().EndsWith(".gif") || imageUrl.ToLower().EndsWith(".png") || imageUrl.ToLower().EndsWith(".jpg") || imageUrl.ToLower().EndsWith(".bmp"))
                            {
                                if (modelType == ObjectModelType.SSOM)
                                {
                                    bitmap = new Bitmap(Path.Combine(imagesUrlFolder, imageUrl));
                                }
                                else
                                {
                                    bitmap = new Bitmap(client.OpenRead(Path.Combine(imagesUrlFolder, imageUrl)));
                                }                                
                            }
                            else if (imageUrl.ToLower().EndsWith(".ico"))
                            {
                                if (modelType == ObjectModelType.SSOM)
                                {
                                    Icon icon = new Icon(Path.Combine(imagesUrlFolder, imageUrl));
                                    bitmap = icon.ToBitmap();
                                }
                                else
                                {
                                    Icon icon = new Icon(client.OpenRead(Path.Combine(imagesUrlFolder, imageUrl)));
                                    bitmap = icon.ToBitmap();
                                }
                            }
                            if (bitmap.Width != 16)
                            {
                                bitmap = new Bitmap(bitmap, 16, 16);
                            }
                            images[imageUrl] = bitmap;
                        }
                    }
                }
                catch (Exception exc)
                {
                    //SPCoderForm.MainForm.LogException(exc);
                }
            }

            SPTreeViewNode node = new SPTreeViewNode { Text = tekst, Tag = o };
            
            if (bitmap != null) node.Image = bitmap;
            return node;
        }

        

        

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            string omType = cbObjectModelType.SelectedItem.ToString();
            Connect(txtUrl.Text, omType);
        }

        private void tvSp_ItemDrag_1(object sender, ItemDragEventArgs e)
        {
            try
            {                
                SPCoderForm.MainForm.DragedBaseNode = ((Node)((TreeNodeAdv[])e.Item)[0].Tag).Tag as BaseNode;                
                if (SPCoderForm.MainForm.DragedBaseNode != null && SPCoderForm.MainForm.DragedBaseNode.SPObject != null)
                {
                    tvSp.DoDragDrop(SPCoderForm.MainForm.DragedBaseNode.SPObject, DragDropEffects.Copy | DragDropEffects.Move);
                }
            }
            catch (Exception exc)
            {
                //this can happen when user tries to drop object to source window
                SPCoderForm.MainForm.LogException(exc);
            }
        }

        public void DisposeNodes()
        {
            foreach (BaseNode node in Nodes)
            {
                DisposeBaseNodes(node);
            }
        }

        private void DisposeBaseNodes(BaseNode node)
        {
            if (node != null)
            {
                if (node != null && node.SPObject != null && node.SPObject is IDisposable)
                {
                    try
                    {
                        ((IDisposable)node.SPObject).Dispose();
                    }
                    catch (Exception)
                    {
                        //just skip this
                    }
                }

                foreach (BaseNode treeNode in node.Children)
                {
                    DisposeBaseNodes(treeNode);
                }
            }
        }

        private void txtUrl_KeyPress(object sender, KeyPressEventArgs e)
        {            
            if (e.KeyChar == (char)Keys.Enter)
            {
                toolStripButton1_Click(sender, null);
            }
        }

        private void ExplorerView_Load(object sender, EventArgs e)
        {
            if (cbObjectModelType != null && cbObjectModelType.Items.Count > 1)
                cbObjectModelType.SelectedIndex = 0;
        }

    }
}
